const express = require("express");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcryptjs");
const User = require("../models/User");

const router = express.Router();
const authMiddleware = require("../middleware/auth");

function signToken(userId, secret, expiresIn, tokenVersion) {
  return jwt.sign({ sub: userId, ver: tokenVersion || 0 }, secret, {
    expiresIn,
  });
}

router.post("/register", async (req, res) => {
  try {
    const { email, username, password } = req.body || {};
    if (!email || !username || !password) {
      return res
        .status(400)
        .json({ message: "缺少必要字段: email / username / password" });
    }

    const emailRegex = /.+@.+\..+/;
    if (!emailRegex.test(email)) {
      return res.status(400).json({ message: "邮箱格式不正确" });
    }
    if (String(username).length < 3) {
      return res.status(400).json({ message: "用户名长度至少为 3" });
    }
    if (String(password).length < 6) {
      return res.status(400).json({ message: "密码长度至少为 6" });
    }

    const existing = await User.findOne({ $or: [{ email }, { username }] });
    if (existing) {
      return res.status(409).json({ message: "用户名或邮箱已被注册" });
    }

    const salt = await bcrypt.genSalt(10);
    const passwordHash = await bcrypt.hash(password, salt);

    const user = await User.create({ email, username, passwordHash });
    return res.status(201).json({
      id: user._id,
      email: user.email,
      username: user.username,
      createdAt: user.createdAt,
    });
  } catch (err) {
    console.error(err);
    return res.status(500).json({ message: "服务器错误" });
  }
});

router.post("/login", async (req, res) => {
  try {
    const { identifier, password } = req.body || {};
    if (!identifier || !password) {
      return res
        .status(400)
        .json({ message: "缺少必要字段: identifier / password" });
    }

    const user = await User.findOne({
      $or: [{ username: identifier }, { email: identifier }],
    });
    if (!user) {
      return res.status(401).json({ message: "用户名或密码错误" });
    }

    const ok = await user.comparePassword(password);
    if (!ok) {
      return res.status(401).json({ message: "用户名或密码错误" });
    }

    const accessSecret =
      process.env.ACCESS_TOKEN_SECRET ||
      process.env.JWT_SECRET ||
      "dev_access_secret";
    const accessExpiresIn = process.env.ACCESS_TOKEN_EXPIRES_IN || "1h";
    const refreshSecret =
      process.env.REFRESH_TOKEN_SECRET || "dev_refresh_secret";
    const refreshExpiresIn = process.env.REFRESH_TOKEN_EXPIRES_IN || "7d";

    const accessToken = signToken(
      user._id.toString(),
      accessSecret,
      accessExpiresIn,
      user.tokenVersion || 0
    );
    const refreshToken = signToken(
      user._id.toString(),
      refreshSecret,
      refreshExpiresIn,
      user.tokenVersion || 0
    );

    // 通过 HttpOnly Cookie 下发刷新令牌
    const isProd = process.env.NODE_ENV === "production";
    res.cookie("refreshToken", refreshToken, {
      httpOnly: true,
      secure: isProd,
      sameSite: isProd ? "none" : "lax",
      maxAge: 7 * 24 * 60 * 60 * 1000, // 7 天
      path: "/",
    });

    return res.status(200).json({
      accessToken,
      user: {
        id: user._id,
        email: user.email,
        username: user.username,
      },
    });
  } catch (err) {
    console.error(err);
    return res.status(500).json({ message: "服务器错误" });
  }
});

module.exports = router;

// 受保护接口：获取当前用户信息
router.get("/me", authMiddleware, async (req, res) => {
  return res.status(200).json({ user: req.user });
});

// 刷新访问令牌
router.post("/refresh", async (req, res) => {
  try {
    const fromCookie = (req.cookies && req.cookies.refreshToken) || null;
    const fromBody = (req.body && req.body.refreshToken) || null;
    const refreshToken = fromCookie || fromBody;
    if (!refreshToken) {
      return res.status(400).json({ message: "缺少刷新令牌" });
    }

    const refreshSecret =
      process.env.REFRESH_TOKEN_SECRET || "dev_refresh_secret";
    const payload = jwt.verify(refreshToken, refreshSecret);
    const userId = payload && payload.sub;
    if (!userId) {
      return res.status(401).json({ message: "无效的刷新令牌" });
    }

    const user = await User.findById(userId).lean();
    if (!user) {
      return res.status(401).json({ message: "用户不存在或已被删除" });
    }

    // 校验 tokenVersion 一致
    if ((payload && payload.ver) !== (user.tokenVersion || 0)) {
      return res.status(401).json({ message: "刷新令牌已失效" });
    }

    const accessSecret =
      process.env.ACCESS_TOKEN_SECRET ||
      process.env.JWT_SECRET ||
      "dev_access_secret";
    const accessExpiresIn = process.env.ACCESS_TOKEN_EXPIRES_IN || "1h";
    const newAccessToken = signToken(
      userId.toString(),
      accessSecret,
      accessExpiresIn,
      user.tokenVersion || 0
    );

    return res.status(200).json({
      accessToken: newAccessToken,
      user: {
        id: user._id,
        email: user.email,
        username: user.username,
      },
    });
  } catch (err) {
    console.error(err);
    return res.status(401).json({ message: "刷新失败或令牌无效" });
  }
});

// 修改密码（受保护）
router.post("/change-password", authMiddleware, async (req, res) => {
  try {
    const { oldPassword, newPassword } = req.body || {};
    if (!oldPassword || !newPassword) {
      return res
        .status(400)
        .json({ message: "缺少必要字段: oldPassword / newPassword" });
    }
    if (String(newPassword).length < 6) {
      return res.status(400).json({ message: "新密码长度至少为 6" });
    }

    const user = await User.findById(req.user.id);
    if (!user) {
      return res.status(404).json({ message: "用户不存在" });
    }

    const ok = await user.comparePassword(oldPassword);
    if (!ok) {
      return res.status(401).json({ message: "旧密码不正确" });
    }

    const salt = await bcrypt.genSalt(10);
    user.passwordHash = await bcrypt.hash(newPassword, salt);
    // 自增 tokenVersion，使已签发 token 立即失效
    user.tokenVersion = (user.tokenVersion || 0) + 1;
    await user.save();

    // 清理旧的刷新 Cookie，避免继续刷新
    const isProd = process.env.NODE_ENV === "production";
    res.cookie("refreshToken", "", {
      httpOnly: true,
      secure: isProd,
      sameSite: isProd ? "none" : "lax",
      maxAge: 0,
      path: "/",
    });

    return res.status(200).json({ message: "密码已更新，已注销其他会话" });
  } catch (err) {
    console.error(err);
    return res.status(500).json({ message: "服务器错误" });
  }
});

// 修改当前用户信息（受保护）
router.patch("/me", authMiddleware, async (req, res) => {
  try {
    const { email, username } = req.body || {};
    if (!email && !username) {
      return res
        .status(400)
        .json({ message: "至少提供一个可更新字段: email 或 username" });
    }

    const updates = {};
    if (email) {
      const emailRegex = /.+@.+\..+/;
      if (!emailRegex.test(email)) {
        return res.status(400).json({ message: "邮箱格式不正确" });
      }
      updates.email = email;
    }
    if (username) {
      if (String(username).length < 3) {
        return res.status(400).json({ message: "用户名长度至少为 3" });
      }
      updates.username = username;
    }

    // 检查唯一性冲突
    if (updates.email || updates.username) {
      const conflict = await User.findOne({
        _id: { $ne: req.user.id },
        $or: [
          updates.email ? { email: updates.email } : null,
          updates.username ? { username: updates.username } : null,
        ].filter(Boolean),
      }).lean();
      if (conflict) {
        return res.status(409).json({ message: "用户名或邮箱已被占用" });
      }
    }

    const user = await User.findByIdAndUpdate(
      req.user.id,
      { $set: updates },
      { new: true }
    ).lean();

    if (!user) {
      return res.status(404).json({ message: "用户不存在" });
    }

    return res.status(200).json({
      user: {
        id: user._id,
        email: user.email,
        username: user.username,
      },
    });
  } catch (err) {
    console.error(err);
    return res.status(500).json({ message: "服务器错误" });
  }
});
